using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.Win32;
using System.Runtime.InteropServices;

namespace HostsEditor
{
    public partial class form_Main : Form
    {
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wParam, Int32 lParam);

        private bool saved = true;
        private bool Saved
        {
            get { return saved; }
            set
            {
                if (saved != value)
                {
                    saved = value;
                    this.strip_StatusLineSaved.Text = saved ? "Status: Saved" : "Status: NOT Saved";
                }
            }
        }
        HostCollection hosts = new HostCollection();

        public form_Main()
        {
            InitializeComponent();
            this.Icon = HostsEditor.Properties.Resources.editIcon;
            this.strip_StatusLineSaved.Text = "Status: Saved";

            LoadList();
        }

        private void SetRedraw(Control control, bool state)
        {
            const int WM_SETREDRAW = 11;
            SendMessage(control.Handle, WM_SETREDRAW, state, 0);
        }

        private void LoadList()
        {
            SetRedraw(listView, false);

            listView.Items.Clear();
            hosts.Load();

            ListViewGroup currentGroup = null;

            string[] tmpHostText = new string[3];
            foreach (Host item in hosts)
            {
                //                if (item.IsComment && )
                //                    continue;

                if (item.IsComment)
                {
                    tmpHostText[0] = item.Comment;
                    tmpHostText[1] = null;
                    tmpHostText[2] = null;
                }
                else
                {
                    tmpHostText[0] = item.IP;
                    tmpHostText[1] = item.HostName;
                    tmpHostText[2] = item.Comment;
                }

                ListViewItem tmpLVItem = new ListViewItem(tmpHostText);
                tmpLVItem.Group = currentGroup;
                tmpLVItem.Tag = item;
                tmpLVItem.Checked = item.Enabled;

                listView.Items.Add(tmpLVItem);
            }

            SetRedraw(listView, true);

            Saved = true;
        }

        private void Add()
        {
            string[] LVItemValue = new string[3];
            form_AddEdit form = new form_AddEdit();
            ListViewItem LVItem;
            Host host;
            if (form.ShowDialog() == DialogResult.OK)
            {
                host = new Host(form.cbox_Enable.Checked, form.tbox_IP.Text, form.tbox_Domaine.Text, form.tbox_Comment.Text);
                LVItemValue[0] = host.IP;
                LVItemValue[1] = host.HostName;
                LVItemValue[2] = host.Comment;


                LVItem = new ListViewItem(LVItemValue);
                LVItem.Checked = form.cbox_Enable.Checked;
                LVItem.Tag = host;
                listView.Items.Add(LVItem);
                hosts.Add(host);

                if (form.cbox_Copy.Checked && string.Compare(form.tbox_Domaine.Text.Substring(0, 4), "www.") != 0)
                {
                    host = new Host(form.cbox_Enable.Checked, form.tbox_IP.Text, "www." + form.tbox_Domaine.Text, form.tbox_Comment.Text);
                    LVItemValue[0] = host.IP;
                    LVItemValue[1] = host.HostName;
                    LVItemValue[2] = host.Comment;

                    LVItem = new ListViewItem(LVItemValue);
                    LVItem.Checked = form.cbox_Enable.Checked;
                    LVItem.Tag = host;
                    listView.Items.Add(LVItem);
                    hosts.Add(host);
                }
                Saved = false;
            }
        }

        private void Edit()
        {
            string[] LVItemValue = new string[3];
            form_AddEdit form = null;

            int i = 0;
            for (i = 0; i < listView.Items.Count; i++)
            {
                if (listView.Items[i].Selected)
                {
                    form = new form_AddEdit((Host)listView.Items[i].Tag);
                    break;
                }
            }

            if (form == null)
                return;

            Host host;
            ListViewItem LVItem;

            if (form.ShowDialog() == DialogResult.OK)
            {
                LVItemValue[1] = form.tbox_Domaine.Text;
                LVItemValue[0] = form.tbox_IP.Text;
                LVItemValue[2] = form.tbox_Comment.Text;

                host = (Host)listView.Items[i].Tag;

                listView.Items[i].Remove();

                host.IP = form.tbox_IP.Text;
                host.HostName = form.tbox_Domaine.Text;
                host.Comment = form.tbox_Comment.Text;
                host.Enabled = form.cbox_Enable.Checked;

                LVItem = new ListViewItem(LVItemValue);
                LVItem.Checked = form.cbox_Enable.Checked;
                LVItem.Tag = host;

                listView.Items.Insert(i, LVItem);

                Saved = false;
            }
        }

        private void Delete()
        {
            if (listView.SelectedItems.Count > 0)
            {
                List<ListViewItem> selectedItems = new List<ListViewItem>();
                for (int i = 0; i < listView.SelectedItems.Count; i++)
                    selectedItems.Add(listView.SelectedItems[i]);

                ListViewItem LVItem;
                for (int i = 0; i < selectedItems.Count; i++)
                {
                    LVItem = selectedItems[i];
                    listView.Items.Remove(LVItem);

                    hosts.Remove((Host)LVItem.Tag);
                }
                Saved = false;
            }
        }

        private void Save()
        {
            try
            {
                Saved = hosts.Save();
            }
            catch
            {
                MessageBox.Show("Unknow error ouccured when saving file. File not saved.", "Warning!", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void strip_MainMenuToolsReload_Click(object sender, EventArgs e)
        {
            if (!saved)
            {
                if (MessageBox.Show("All changes will be lost! Reload list?", "Warning!!!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                    LoadList();
            }
            else
            {
                LoadList();
            }

        }

        private void strip_MainMenuToolsEditItem_Click(object sender, EventArgs e)
        {
            Edit();
        }

        private void strip_MainMenuToolsAddItem_Click(object sender, EventArgs e)
        {
            Add();
        }

        private void strip_MainMenuToolsDeleteItem_Click(object sender, EventArgs e)
        {
            Delete();
        }

        private void strip_MainMenuToolsSave_Click(object sender, EventArgs e)
        {
            Save();
        }


        private void form_Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!Saved)
                if (MessageBox.Show("Hosts file are not saved. Save file before close?", "Warning!", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
                    strip_MainMenuToolsSave_Click(null, null);
        }

        private void strip_MainMenuToolsAbout_Click(object sender, EventArgs e)
        {
            (new form_AboutBox()).ShowDialog();
        }

        private void strip_MainMenuToolsEditManualy_Click(object sender, EventArgs e)
        {
            string notepad = "%SystemRoot%\\notepad.exe";
            notepad = Environment.ExpandEnvironmentVariables(notepad);
            System.Diagnostics.Process.Start(notepad, hosts.HostsFile.FullName);
        }

        private void listView_KeyUp(object sender, KeyEventArgs e)
        {
            //Edit first selected item
            if (e.Modifiers == Keys.Alt && e.KeyCode == Keys.Enter)
            {
                Edit();
            }
            //Edit first selected item
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.E)
            {
                Edit();
            }
            //Delete selected items
            else if (e.KeyCode == Keys.Delete)
            {
                Delete();
            }
            //Add new item
            else if (e.KeyCode == Keys.Insert)
            {
                Add();
            }
            //Save list
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.S)
            {
                Save();
            }
            //Reload list
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.R)
            {
                LoadList();
            }
            //About
            else if (e.KeyCode == Keys.F1)
            {
                Add();
            }
            //Selecet All
            else if (e.Modifiers == Keys.Control && e.KeyCode == Keys.A)
            {
                foreach (ListViewItem item in listView.Items)
                    item.Selected = true;
            }

            else if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.E)
            {
                strip_MainMenuToolsEditManualy_Click(null, null);
            }
        }

        private void listView_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            Host host = e.Item.Tag as Host;
            ListView lv = sender as ListView;

            if (!host.IsComment)
            {
                e.DrawDefault = true;
                return;
            }

            e.DrawDefault = false;
            e.DrawBackground();

            Font fnt = new Font(lv.Font, FontStyle.Bold);
            e.Graphics.DrawString(e.Item.Text, fnt, new SolidBrush(SystemColors.WindowText), e.Bounds.Left + 4, e.Bounds.Top + 2);

            e.DrawFocusRectangle();
        }

        private void listView_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
        {
            e.DrawDefault = true;
        }

        private void txtIPRecent_OnClick(object sender, EventArgs e)
        {
            ToolStripMenuItem mi = sender as ToolStripMenuItem;
            foreach (ListViewItem item in listView.SelectedItems)
            {
                Host host = item.Tag as Host;
                if (host.IsComment)
                    continue;

                item.SubItems[0].Text = mi.Text;
                host.IP = mi.Text;
                Saved = false;
            }
        }

        private void txtIP_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                foreach (ListViewItem item in listView.SelectedItems)
                {
                    Host host = item.Tag as Host;
                    if (host.IsComment)
                        continue;

                    item.SubItems[0].Text = txtIP.Text;
                    host.IP = txtIP.Text;
                    Saved = false;
                }

                contextMenuStrip1.Hide();
                contextMenuStrip1.Items.Insert(0, new ToolStripMenuItem(txtIP.Text, null, new EventHandler(this.txtIPRecent_OnClick)));
                listView.Focus();
            }
        }

        private void listView_ItemChecked(object sender, ItemCheckedEventArgs e)
        {
            Host host = e.Item.Tag as Host;
            if (host.IsComment)
                return;

            host.Enabled = e.Item.Checked;
            Saved = false;
        }

        private void toolStripMenuItem1_Click(object sender, EventArgs e)
        {

        }

        private void strip_MainMenuToolsFindNext_Click(object sender, EventArgs e)
        {
            string search = strip_MainMenuToolsSearchText.Text.ToLower();
            for (int i = listView.FocusedItem.Index + 1; i < listView.Items.Count; ++i)
            {
                ListViewItem item = listView.Items[i];

                if (item.SubItems[0].Text.ToLower().IndexOf(search) != -1 ||
                    item.SubItems[1].Text.ToLower().IndexOf(search) != -1 ||
                    item.SubItems[2].Text.ToLower().IndexOf(search) != -1)
                {
                    listView.EnsureVisible(item.Index);
                    listView.FocusedItem = item;
                    break;
                }
            }
        }

        private void strip_MainMenuToolsFindPrev_Click(object sender, EventArgs e)
        {
            string search = strip_MainMenuToolsSearchText.Text.ToLower();
            for (int i = listView.FocusedItem.Index - 1; i >= 0; --i)
            {
                ListViewItem item = listView.Items[i];

                if (item.SubItems[0].Text.ToLower().IndexOf(search) != -1 ||
                    item.SubItems[1].Text.ToLower().IndexOf(search) != -1 ||
                    item.SubItems[2].Text.ToLower().IndexOf(search) != -1)
                {
                    listView.EnsureVisible(item.Index);
                    listView.FocusedItem = item;
                    break;
                }
            }
        }

        private void strip_MainMenuToolsSearchText_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                strip_MainMenuToolsFindNext_Click(null, new EventArgs());
            }
        }
    }
}
